/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.object;

import net.worlds.WorldsException;
import net.worlds.Main;
import net.worlds.PropChangeHandler;
import org.jbox2d.common.Vec2D;
import org.jbox2d.dynamics.joints.JointDef;


public abstract class Joint extends GameObject{
    protected org.jbox2d.dynamics.joints.Joint joint;
    protected JointDef jointDef;
    protected Part part1;
    protected Part part2;
    protected Vec2D anchor;
    public Joint(String type) throws WorldsException
    {
        super(type);
        worldLocked = true;
        addPropChangeHandler("Part1", new PropChangeHandler()
        {

            @Override
            public void handle(final Object oldValue, final Object value) throws WorldsException {
                try {
                    if (!(value instanceof Part)) {
                        setProp("Part1", oldValue, false);
                    }
                    if (inWorld) {
                        setProp("Part1", oldValue, false);
                    } else {
                        part1 = (Part) value;
                    }
                } catch (WorldsException ex) {
                    ex.printStackTrace();
                }
            }
        });
        addPropChangeHandler("Part2", new PropChangeHandler()
        {

            @Override
            public void handle(Object oldValue, Object value) throws WorldsException {
                if(!(value instanceof Part))
                {
                    setProp("Part2", oldValue, false);
                }
                if(inWorld)
                    setProp("Part2", oldValue, false);
                else
                    part2 = (Part) value;

            }

        });
        addPropChangeHandler("Anchor", new PropChangeHandler()
        {

            @Override
            public void handle(Object oldValue, Object value) throws WorldsException {
                if(inWorld)
                    setProp("Anchor", oldValue, false);
                else
                    anchor = (Vec2D) value;
            }

        });
    }
    public Part getPart1()
    {
        return part1;
    }
    public Part getPart2()
    {
        return part2;
    }
    public Part getOtherPart(Part p)
    {
        if(p == part1)
            return part2;
        else if(p == part2)
            return part1;
        else
            return null;
    }
    public org.jbox2d.dynamics.joints.Joint getJoint()
    {
        return joint;
    }
    @Override
    public void addToWorld() throws WorldsException
    {
        if(part1 == null || part2 == null)
            return;
        if(!part1.isInWorld())
        {
            part1.addAction(new Runnable()
            {
                public void run() {
                    try {
                        addToWorld();
                    } catch (WorldsException ex) {
                        Main.error(ex);
                    }
                }
            });
        }
        else if(!part2.isInWorld())
        {
            part2.addAction(new Runnable()
            {
                public void run() {
                    try {
                        addToWorld();
                    } catch (WorldsException ex) {
                        Main.error(ex);
                    }
                }
            });
        }
        else
        {
            
            part1.addJoint(this);
            part2.addJoint(this);
            createJoint();
        }
        try
        {
            if(!inWorld)
            {
                super.addToWorld();
            }
        }
        catch(Exception ex)
        {
            Main.error(ex);
        }
    }
    @Override
    public Object getProp(String k) throws WorldsException
    {
        if((k.equals("Anchor") || k.equals("Anchor1")) && inWorld && (joint != null||(this instanceof Weld)))
        {
            if(this instanceof Hinge || this instanceof SimpleWeld)
                return new Vec2D(joint.getAnchor1());
            else if((this instanceof Weld))
                return ((Weld)this).getAnchor1();
            else
                return ((Rope)this).getAnchor1();
        }
        else if(k.equals("Anchor2") && this instanceof Rope && inWorld)
        {
            return ((Rope)this).getAnchor2();
        }
        else
        {
            return super.getProp(k);
        }
    }
    @Override
    public void step() throws WorldsException
    {
        if(joint != null && !joint.isDead)
        {
            setProp("Anchor", new Vec2D(joint.getAnchor1()), false);
            anchor = new Vec2D(joint.getAnchor1());
        }
    }
    @Override
    public void destructor() throws WorldsException
    {
        super.destructor();
        destroyJoint();
        removeFromParts();
    }
    public void destroyJoint()
    {
        if(joint != null && !joint.isDead)
        {
            world.destroyJoint(joint);
            joint = null;
        }
    }
    public void setAnchor()
    {
        if(part1 != null && part1.getBody() != null && joint != null)
            anchor = new Vec2D(joint.getAnchor1());
    }
    public void removeFromParts()
    {
        part1.removeJoint(this);
        part2.removeJoint(this);
    }
    protected void wakeupParts()
    {
        if(part1 != null && part1.getBody() != null)
            part1.getBody().wakeUp();
        if(part2 != null && part2.getBody() != null)
            part2.getBody().wakeUp();
    }
    protected abstract void createJoint() throws WorldsException;
}
